/**
 * @author siwi
 * @email [example@mail.com]
 * @create date 2018-03-14 12:24:20
 * @modify date 2018-03-14 12:24:20
 * @desc [缓存模块 封装redis缓存 文件缓存]
 */
const Promise = require('bluebird')
const fs = require('fs')
const path = require('path')
const Redis = require('ioredis')

let instance = null
class Cache {
    constructor(options) {
        this.options = options
        this.drive = options['drive']
        if (!instance) {
            instance = this
        }
        return instance
    }
    /**
     * 设置缓存
     * @param {String} key 
     * @param {String Json} value 
     * @param {int} seconds 
     */
    async put(key, value, seconds = -1) {
        let res
        if (this.drive == 'file') {
            res = await this.write(key, value, seconds)
        } else {
            res = await this.setex(key, value, seconds)
        }
        return res
    }

    /**
     * 读取缓存
     * @param {String} key 
     */
    async get(key) {
        if (this.drive == 'file') {
            const cache_file = path.join(this.options['file']['path'], `${key}.json`)
            if (!fs.existsSync(cache_file)) {
                return false
            }
            const content = fs.readFileSync(cache_file)
            try {
                const data = JSON.parse(content.toString('utf8'))
                const invalid = data['expire'] == -1 ? true : data['expire'] - Math.floor(Date.now() / 1000)
                console.log(invalid)
                if (invalid > 0) {
                    return data['value']
                }
                fs.unlinkSync(cache_file)
                return false
            } catch (error) {
                console.log(error)
            }
        } else {
            const redis = new Redis(this.options)
            const res = await redis.get(key)
            await redis.quit()
            return res
        }
    }

    /**
     * 删除缓存
     * @param {String} key 
     */
    async forget(key) {
        if (this.drive == 'file') {
            const cache_file = path.join(this.options['file']['path'], `${key}.json`)
            fs.unlinkSync(cache_file)
            return true
        } else {
            const redis = new Redis(this.options)
            const res = await redis.del(key)
            await redis.quit()
            return res
        }
    }

    /**
     * 文件缓存
     * @param {*} key 
     * @param {*} seconds 
     * @param {*} value 
     */
    async write(key, value, seconds) {
        const data = {
            value: value,
            expire: Math.floor(Date.now() / 1000) + seconds
        }
        const cache_file = path.join(this.options['file']['path'], `${key}.json`)
        if (!fs.existsSync(this.options['file']['path'])) {
            fs.mkdirSync(this.options['file']['path'])
        }
        const options = {
            flags: 'w',
            encoding: 'utf8',
            fd: null,
            mode: 0o666,
            autoClose: true
        }
        const stream = fs.createWriteStream(cache_file, options)
        return new Promise((resolve, reject) => {
            const res = stream.write(JSON.stringify(data))
            console.log(res)
            resolve(res)
        })

    }

    /**
     * redis setex
     * @param {*} key 
     * @param {*} value 
     * @param {*} seconds 
     */
    async setex(key, value, seconds) {
        const redis = new ioredis(this.options)
        let res
        if (seconds == -1) {
            res = await redis.set(key, value)
        }
        res = await redis.setex(key, seconds, value)
        await redis.quit()
        return res
    }
}
module.exports = Cache